﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using BakalarskaPraca.Forms;
using BakalarskaPraca.Generation.Data;
using Microsoft.DirectX;

namespace BakalarskaPraca.Generation.Tasks
{
    public class PlantSimulationPlantDistributionGeneration : PlantDistributionGenerationBase
    {
        public int PlantSeedCount;
        public int SimulationIterationCount;

        public PlantSimulationPlantDistributionGeneration(List<HumidityPolygon> polygons, ModelData modelData) : base(polygons, modelData)
        {
            this.SimulationIterationCount = Properties.Settings.Default.PlantSimulationIterations;
            this.PlantSeedCount = Properties.Settings.Default.PlantSeedCount;
        }

        protected override string Name
        {
            get { return "simulating plants"; }
        }

        protected override void  Populate()
        {
            this.Plants = new List<Plant>();
            for (int i = 0; i < this.PlantSeedCount; i++)
            {
                Plant p = this.PlantSeed();
                if (p != null)
                    this.Plants.Add(p);
            }
            for (int i = 0; i < this.SimulationIterationCount; i++)
            {
                if (this.Plants.Any())
                {
                    this.SimulateForOneIteration();
                    this.Reporter.ReportProgress(i + 1, this.SimulationIterationCount);
                }
                else break;
            }
        }

        private void SimulateForOneIteration()
        {
            this.Plants.ForEach(plant => plant.Grow(1));
            this.Plants.RemoveAll(plant => plant.Dead);
            List<Plant> newPlants = this.Plants
                .Where(plant => plant.CanReproduce())
                .SelectMany(this.ReproducePlant).ToList();

            this.Plants.AddRange(newPlants);
        }

        private List<Plant> ReproducePlant(Plant plant)
        {
            List<Plant> result = new List<Plant>();
            if (this.RandomGenerator.NextDouble() < plant.PlantData.ReproductionProbability)
            {
                plant.LastReproductionCycle = plant.Age;
                int radius = plant.PlantData.ReproductionRadius;
                int numChildrens = this.RandomGenerator.Next(plant.PlantData.MaxChildNumbers);
                for (int i = 0; i < numChildrens; i++)
                {
                    int x = this.RandomGenerator.Next(-radius, radius) + (int)plant.X;
                    int y = this.RandomGenerator.Next(-radius, radius) + (int)plant.Y;
                    if (InBounds(y, x) && this.IsFree(x, y))
                    {
                        int humidity = this.GetHumidityValue(x, y);
                        Plant child = new Plant();
                        child.X = x;
                        child.Y = y;
                        child.PlantData = plant.PlantData;
                        if (child.WillSurvive(humidity))
                        {
                            result.Add(child);
                        }
                    }
                }
            }
            return result;
        }
    }
}
